﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using NetTopologySuite.Algorithm;
using NetTopologySuite.Geometries.Utilities;

namespace NetTopologySuite.Operation.Predicate
{
	internal class RectangleIntersectsSegmentVisitor : ShortCircuitedGeometryVisitor
	{
		public RectangleIntersectsSegmentVisitor(IPolygon rectangle)
		{
			this._rectEnv = rectangle.EnvelopeInternal;
			this._rectIntersector = new RectangleLineIntersector(this._rectEnv);
		}

		public bool Intersects { get; private set; }

		protected override void Visit(IGeometry geom)
		{
			Envelope envelopeInternal = geom.EnvelopeInternal;
			if (!this._rectEnv.Intersects(envelopeInternal))
			{
				return;
			}
			ICollection<IGeometry> lines = LinearComponentExtracter.GetLines(geom);
			this.CheckIntersectionWithLineStrings(lines);
		}

		private void CheckIntersectionWithLineStrings(IEnumerable<IGeometry> lines)
		{
			foreach (IGeometry geometry in lines)
			{
				ILineString testLine = (ILineString)geometry;
				this.CheckIntersectionWithSegments(testLine);
				if (this.Intersects)
				{
					break;
				}
			}
		}

		private void CheckIntersectionWithSegments(ICurve testLine)
		{
			ICoordinateSequence coordinateSequence = testLine.CoordinateSequence;
			for (int i = 1; i < coordinateSequence.Count; i++)
			{
				coordinateSequence.GetCoordinate(i - 1, this._p0);
				coordinateSequence.GetCoordinate(i, this._p1);
				if (this._rectIntersector.Intersects(this._p0, this._p1))
				{
					this.Intersects = true;
					return;
				}
			}
		}

		protected override bool IsDone()
		{
			return this.Intersects;
		}

		private readonly Envelope _rectEnv;

		private readonly RectangleLineIntersector _rectIntersector;

		private readonly Coordinate _p0 = new Coordinate();

		private readonly Coordinate _p1 = new Coordinate();
	}
}
